﻿using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Syngine.Components;
using Syngine.Input;
using Syngine.Components.Screens;
#if !(WINDOWS_PHONE || ANDROID)
using Syngine.Input.Mouse;
#endif
using Syngine.Input.Touch;

namespace Syngine
{
	/// <summary>
	/// 
	/// </summary>
	public sealed class GameContext
	{
		#region Fields
		
		private static Game _game;
		private static GameController _gameController;
		private static UserInput _input;
		private static Camera _camera;

		#endregion

		#region Constructors

		static GameContext()
		{
		}

		#endregion

		#region Properties

		/// <summary>
		/// 
		/// </summary>
		public static Game Game
		{
			get
			{
				return _game;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public static GameController GameController
		{
			get
			{
				return _gameController;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public static ScreenController ScreenController
		{
			get
			{
				return _gameController.ScreenController;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public static UserInput Input
		{
			get
			{
				if (_input == null)
				{
					_input = new UserInput();
#if !(WINDOWS_PHONE || ANDROID)
					_input.Set(new MouseHandler());
#else
					_input.Set(new TouchHandler());
#endif
					_input.Initialize();
				}

				return _input;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public static GraphicsDevice GraphicsDevice
		{
			get
			{
				return Game.GraphicsDevice;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public static Camera Camera
		{
			get
			{
				if (_camera == null)
				{
					Set(new Camera());
				}

				return _camera;
			}
		}

		#endregion

		#region Methods

		/// <summary>
		/// 
		/// </summary>
		/// <param name="game"></param>
		public static void Set(Game game)
		{
			Interlocked.Exchange(ref _game, game);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="gameController"></param>
		public static void Set(GameController gameController)
		{
			Interlocked.Exchange(ref _gameController, gameController);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="input"></param>
		public static void Set(UserInput input)
		{
			Interlocked.Exchange(ref _input, input);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="camera"></param>
		public static void Set(Camera camera)
		{
			Interlocked.Exchange(ref _camera, camera);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public static LoadContext CreateLoadContext()
		{
			return new LoadContext(GameController, Game.Content);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public static UpdateContext CreateUpdateContext(GameTime gameTime)
		{
			return new UpdateContext(GameController, gameTime);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public static DrawContext CreateDrawContext(GameTime gameTime)
		{
			return CreateDrawContext(gameTime, false);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public static DrawContext CreateDrawContext(GameTime gameTime, bool newSpriteBatch)
		{
			if (newSpriteBatch)
			{
				return new DrawContext(GameController, new SpriteBatch(Game.GraphicsDevice), gameTime);
			}

			return new DrawContext(GameController, GameController.SpriteBatch, gameTime);
		}

		#endregion
	}
}